using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Drawing;
using Microsoft.DirectX.DirectDraw;

namespace TowerDefense_Dx.Core
{
    public class DxTiledMap
    {
        public class Layer
        {
            public int index;
            public int[,] data;
            public bool isVisible = false;

            public Layer(int rows, int columns, int index, bool isVisible)
            {
                this.index = index;
                this.data = new int[rows, columns];
                this.isVisible = isVisible;
                for (int i = 0; i < data.GetLength(0); i++)
                {
                    for (int j = 0; j < data.GetLength(1); j++)
                    {
                        data[i, j] = -1;
                    }
                }
            }

        }

        public class TM_Texture
        {
            public DxSprite sprite;
            public int index;

            public TM_Texture(DxSprite sprite, int index)
            {
                this.sprite = sprite;
                this.index = index;
            }
        }

        private int _rows;
        public int Rows
        {
            get { return _rows; }
            set { _rows = value; }
        }

        private int _columns;
        public int Columns
        {
            get { return _columns; }
            set { _columns = value; }
        }

        private int _cellWidth;
        public int CellWidth
        {
            get { return _cellWidth; }
            set { _cellWidth = value; }
        }

        private int _cellHeight;

        public int CellHeight
        {
            get { return _cellHeight; }
            set { _cellHeight = value; }
        }

        private int _index;
        public int Index
        {
            get { return _index; }
            set { _index = value; }
        }

        private List<Layer> _layers = new List<Layer>();
        public List<Layer> Layers
        {
            get { return _layers; }
            set { _layers = value; }
        }

        private List<TM_Texture> _textures = new List<TM_Texture>();
        public List<TM_Texture> Textures
        {
            get { return _textures; }
            set { _textures = value; }
        }

        private DxOffscreenPlainSurface _surface;
        public DxOffscreenPlainSurface Surface
        {
            get { return _surface; }
            set { _surface = value; }
        }

        private DxInitGraphics _graphics;
        public DxInitGraphics Graphics
        {
            get { return _graphics; }
            set { _graphics = value; }
        }


        public static DxTiledMap Load(string path, DxInitGraphics graphics)
        {
            XmlDocument doc = new XmlDocument();
            doc.Load(path);

            XmlNode mapNode = doc.SelectSingleNode("//map");
            XmlNodeList layerNodeList = mapNode.SelectNodes("//layer");

            DxTiledMap tiledMap = new DxTiledMap();
            tiledMap.Graphics = graphics;

            // Map Info
            tiledMap._cellWidth = int.Parse(mapNode.Attributes["cellwidth"].Value);
            tiledMap._cellHeight = int.Parse(mapNode.Attributes["cellheight"].Value);
            tiledMap._rows = int.Parse(mapNode.Attributes["cellsy"].Value);
            tiledMap._columns = int.Parse(mapNode.Attributes["cellsx"].Value);
            tiledMap._index = int.Parse(mapNode.Attributes["index"].Value);

            tiledMap.Surface = new DxOffscreenPlainSurface(graphics,
                tiledMap.CellWidth * tiledMap.Columns,
                tiledMap.CellHeight * tiledMap.Rows);

            // Layer
            foreach (XmlNode layerNode in layerNodeList)
            {
                int layerIndex = int.Parse(layerNode.Attributes["index"].Value);
                int iVisible = int.Parse(layerNode.Attributes["visible"].Value);
                Layer layer = new Layer(tiledMap.Rows, tiledMap.Columns, layerIndex, iVisible == 1);
                foreach (XmlNode cell in layerNode.ChildNodes)
                {
                    int x, y;
                    x = int.Parse(cell.Attributes["x"].Value);
                    y = int.Parse(cell.Attributes["y"].Value);
                    int imgIndex = int.Parse(cell.Attributes["img"].Value);
                    layer.data[y, x] = imgIndex;
                }
                tiledMap.Layers.Add(layer);
            }

            // Images
            XmlNodeList imageNodeList = mapNode.SelectNodes("//images");
            foreach (XmlNode imageNode in imageNodeList)
            {
                string imgPath = imageNode.Attributes["filename"].Value;
                DxSprite tmp = new DxSprite("Map/" + imgPath, graphics.GraphicsDevice, tiledMap._cellWidth, tiledMap._cellHeight);
                tiledMap.Textures.Add(new TM_Texture(tmp, 0));
            }

            return tiledMap;
        }

        public void Draw(Surface destSurface,Point position)
        {
            foreach (Layer layer in Layers)
            {
                for (int i = 0; i < layer.data.GetLength(0); i++)
                {
                    for (int j = 0; j < layer.data.GetLength(1); j++)
                    {
                        if (layer.data[i, j] != -1)
                        {
                            int x, y;
                            y = i * CellHeight;
                            x = j * CellWidth;
                            Textures[0].sprite.DrawFast(x, y, layer.data[i, j] + 1, _surface.OffSurface, Microsoft.DirectX.DirectDraw.DrawFastFlags.Wait);
                        }
                    }
                }
            }
            destSurface.DrawFast(position.X, position.Y, _surface.OffSurface, Microsoft.DirectX.DirectDraw.DrawFastFlags.Wait);
        }
    }
}
